package com.mutual.reins.interf.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.mutual.base.exception.BusinessException;
import com.mutual.reins.config.service.IFhPriorityService;
import com.mutual.reins.danger.entity.PrpcDangerDto;
import com.mutual.reins.danger.service.IGeneratePrpcDangerDtoService;
import com.mutual.reins.interf.entity.*;
import com.mutual.reins.interf.service.IGeneratePrpcDangerUnitService;
import com.mutual.reins.interf.service.IReinsInterFlogService;
import com.mutual.reins.interf.service.IReinsPolicyInterfService;
import com.mutual.reins.utils.ReinsCompareRiskUtils;
import com.mutual.reins.utils.constraint.ReinsConst;
import com.mutual.reins.utils.constraint.UserExceptionEnum;
import com.mutual.reins.verify.service.IVerifyInerfService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * 投保单审核通过后 再保生成保单的危险单位，并且回写中间表数据
 * @author pc
 */
@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class GeneratePrpcDangerUnitServiceImpl implements IGeneratePrpcDangerUnitService {

    @Autowired
    private IVerifyInerfService iVerifyInerfService;

    @Autowired
    private IReinsInterFlogService iReinsInterFlogService;
    @Autowired
    private IReinsPolicyInterfService iReinsPolicyInterfService;
    @Autowired
    private IGeneratePrpcDangerDtoService iGeneratePrpcDangerDtoService;

    @Autowired
    private IFhPriorityService iFhPriorityService;
    /**
     * 投保单审核通过后 再保生成保单的危险单位，并且回写中间表数据
     *
     * @param reinsOverPolicyDto 保单审核通过接口数据传输实体
     * @return 核心提交核保调用再保接口返回信息对象
     */
    @Override
    public ReinsStatusDto generatePrpcDangerUnit(ReinsOverPolicyDto reinsOverPolicyDto) {

        log.info("保单审核通过调入时间：{}" , DateUtil.now());
        ReinsStatusDto reinsStatusDto = new ReinsStatusDto();
        ReinsInterFlog reinsInterFlog = new ReinsInterFlog();
        try {
            // 初始化返回信息
            reinsStatusDto.setCerTiNo(reinsOverPolicyDto.getPolicyNo());
            reinsStatusDto.setCerTiType(reinsOverPolicyDto.getCerTiType());
            reinsStatusDto.setStatus("Y");
            //队列数据校验
            String checkResult = iVerifyInerfService.checkHttpServiceUndwrtData(reinsOverPolicyDto);
            if(!"".equals(checkResult)){
                //自动试算 todo 后期有试算接口调用
                /// this.autoReinsTrial(reinsOverPolicyDto.getProposalNo(), "T");
                reinsStatusDto.setStatus(checkResult);
                return reinsStatusDto;
            }
            reinsInterFlog.setCerTiType(reinsOverPolicyDto.getCerTiType());
            reinsInterFlog.setCerTiNo(reinsOverPolicyDto.getPolicyNo());
            reinsInterFlog.setProposalNo(reinsOverPolicyDto.getProposalNo());
            reinsInterFlog.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
            reinsInterFlog.setOperatorCode(reinsOverPolicyDto.getUnderwriteCode());
            reinsInterFlog.setOperatorName(reinsOverPolicyDto.getUnderwriteName());
            reinsInterFlog.setOperatorDate(LocalDate.parse(reinsOverPolicyDto.getUnderWriteEndDateStr(), DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            // 初始化中间再保日志表为不通过状态
            reinsInterFlog.setRecordFlag("0");
            // 生成再保日志表，中间表，再保危险单位，分保试算，分保单，分保复核信息
            overwriteAndGenReinsData(reinsOverPolicyDto, reinsInterFlog);
        } catch (BusinessException e) {
            reinsStatusDto.setStatus("N");
            throw new BusinessException(UserExceptionEnum.REINS_INTERF_MESSAGE.getCode(),UserExceptionEnum.REINS_INTERF_MESSAGE.getMessage());
        }
        log.info("保单审核通过调出时间：{}" , DateUtil.now());
        return reinsStatusDto;
    }

    /**
     * 生成再保日志表，中间表，再保危险单位，分保试算，分保单，分保复核信息
     * @param reinsOverPolicyDto 保单审核通过接口数据传输实体
     * @param reinsInterFlog 日志对象
     */
    private void overwriteAndGenReinsData(ReinsOverPolicyDto reinsOverPolicyDto, ReinsInterFlog reinsInterFlog) {
        //更新中间表数据 生成保单危险单位 生成分保单 生成分保单复核数据
        ReinsPolicyInterfDto reinsPolicyInterfDto;

        // 生成日志表
        try {
            log.info(">>>>>>>>>>保单号：{} 日志表初始化 begin >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
            // 查询序号
            Integer amxSerialNo = iReinsInterFlogService.selectMaxSerialNo(reinsOverPolicyDto.getPolicyNo());
            reinsInterFlog.setSerialNo(amxSerialNo+1);
            // 插入记录
            iReinsInterFlogService.save(reinsInterFlog);
            log.info(">>>>>>>>>>保单号：{} 日志表初始化 end >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
        } catch (BusinessException e) {
            log.error("审核通过环节：保单号：{}日志表初始化错误" , reinsOverPolicyDto.getPolicyNo() );
            throw new BusinessException(UserExceptionEnum.REINS_SAVE_REINSINTERFLOG.getCode(),UserExceptionEnum.REINS_SAVE_REINSINTERFLOG.getMessage());
        }
        // 投保单审核通过后再保中间表根据投保单中间更新成保单中间表
        try {
            log.info(">>>>>>>>>>保单号：{}中间表生成 begin >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
            // 回写中间表数据reinspolicyunit LJ
            reinsPolicyInterfDto = iReinsPolicyInterfService.selectReinsPolicyInterf(reinsOverPolicyDto.getProposalNo());
            this.updateReinsPolicyInterfDto(reinsPolicyInterfDto,reinsOverPolicyDto);
            // 先删除数据
            iReinsPolicyInterfService.deleteReinsPolicyInterf("PROPOSALNO",reinsOverPolicyDto.getProposalNo());

            // 再插入数据
            iReinsPolicyInterfService.saveReinsPolicyInterf(reinsPolicyInterfDto);
            log.info(">>>>>>>>>>保单号：{}中间表生成 end >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
        } catch (BusinessException exception) {
            log.error("审核通过环节：保单号：{}中间表生成新错误",reinsOverPolicyDto.getProposalNo());
            throw new BusinessException(UserExceptionEnum.REINS_SAVE_REINSPOLICYINTERF.getCode(),UserExceptionEnum.REINS_SAVE_REINSPOLICYINTERF.getMessage());
        }
        try {
            //从联不生成危险单位及后续数据
            if(reinsPolicyInterfDto.getReinsPolicyUnit().getCoinsFlag().equals(ReinsConst.COINSFLAG_CL)){
                return;
            }
            //确定是否离线计算
            boolean ifOffLineCal = iFhPriorityService.ifTreatyValid(String.valueOf(reinsPolicyInterfDto.getReinsPolicyUnit().getStartDate().getYear()));
            //需要离线计算,则不进行分保试算
            if(!ifOffLineCal){
                //TODO 调用投保单试算生成
///                if(ReinsCompareRiskUtils.isPMLTrialClass(classCode))
///                {
///                    new BLYJReinsTrialAction().simulateRepolicyByDangerNo(proposalNo, "T", dbManager);
///                }else{
///                    new BLReinsTrialAction().simulateRepolicyByDangerNo(proposalNo,"T", dbManager);
///                }
            }
            this.reinsRepolicyCal(reinsPolicyInterfDto,reinsOverPolicyDto,ifOffLineCal);
        } catch (BusinessException exception) {
            exception.printStackTrace();
            log.error("审核通过环节：投保单号：{}审核通过再保数据生成错误", reinsOverPolicyDto.getProposalNo());
            throw exception;
        }
    }

    /**
     * 投保单转保单 生成再保系统危险单位、试算、分保单、复核试算
     * @param reinsPolicyInterfDto 接口表数据
     * @param reinsOverPolicyDto 保单审核通过接口数据传输实体
     * @param ifOffLineCal 是否离线计算
     */
    private void reinsRepolicyCal(ReinsPolicyInterfDto reinsPolicyInterfDto,ReinsOverPolicyDto reinsOverPolicyDto,boolean ifOffLineCal) {
        PrpcDangerDto prpcDangerDto;
        Map<String ,ReinsPolicyUnit>  reinsPolicyUnitMap = new HashMap<String ,ReinsPolicyUnit>(16){{
            put(reinsPolicyInterfDto.getReinsPolicyUnit().getProposalNo(),reinsPolicyInterfDto.getReinsPolicyUnit());
        }};
        // 生成保单危险单位数据并插入
        log.info(">>>>>>>>>> {} 危险单位生成 begin >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
        prpcDangerDto = iGeneratePrpcDangerDtoService.prptDangerDtoToPrpcDangerDto(reinsPolicyUnitMap,ifOffLineCal);
        log.info(">>>>>>>>>> {} 危险单位生成 end >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
        //todo 调用保单危险单位生成方法
        log.info(">>>>>>>>>> {} 试算生成 begin >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
        log.info(">>>>>>>>>> {} 试算生成 end >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());

        //分保单生成
        log.info(">>>>>>>>>> {} 分保单生成 begin >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());

        log.info(">>>>>>>>>> {} 分保单生成 end >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
        //复核数据生成
        log.info(">>>>>>>>>> {} 复核数据生成 begin >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
        log.info(">>>>>>>>>> {} 复核数据生成 end >>>>>>>>>>>" , reinsOverPolicyDto.getPolicyNo());
    }

    /**
     * 更新再保系统中间表
     * @param reinsPolicyInterfDto 中间表数据
     * @param reinsOverPolicyDto 保单审核通过接口数据传输实体
     */
    private void updateReinsPolicyInterfDto(ReinsPolicyInterfDto reinsPolicyInterfDto, ReinsOverPolicyDto reinsOverPolicyDto) {
        if(ObjectUtil.isNotNull(reinsPolicyInterfDto.getReinsPolicyUnit())){
            //更新unit表
            reinsPolicyInterfDto.getReinsPolicyUnit().setPolicyNo(reinsOverPolicyDto.getPolicyNo());
            reinsPolicyInterfDto.getReinsPolicyUnit().setCerTiType(reinsOverPolicyDto.getCerTiType());
            reinsPolicyInterfDto.getReinsPolicyUnit().setUnderWriteCode(reinsOverPolicyDto.getUnderwriteCode());
            reinsPolicyInterfDto.getReinsPolicyUnit().setUnderWriteEndDate(LocalDate.parse(reinsOverPolicyDto.getUnderWriteEndDateStr(),DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            reinsPolicyInterfDto.getReinsPolicyUnit().setUnderWritEname(reinsOverPolicyDto.getUnderwriteName());
        }else{
            throw new BusinessException("保单号"+reinsOverPolicyDto.getProposalNo()+"未能正常查询ReinsPolicyUnitDto数据");
        }
        if(ObjectUtil.isNotNull(reinsPolicyInterfDto.getReinsPolicyItem())  && ! reinsPolicyInterfDto.getReinsPolicyItem().isEmpty()){
            // 更新中间表Item
            for(ReinsPolicyItem reinsPolicyItem:reinsPolicyInterfDto.getReinsPolicyItem()){
                reinsPolicyItem.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
            }
        }else{
            throw new BusinessException("保单号"+reinsOverPolicyDto.getProposalNo()+"未能正常查询reinsPolicyItemDto数据");
        }

        if(ObjectUtil.isNotNull(reinsPolicyInterfDto.getReinsPolicyFee()) && ! reinsPolicyInterfDto.getReinsPolicyFee().isEmpty()){
            // 更新中间表Fee
            for(ReinsPolicyFee reinsPolicyFee:reinsPolicyInterfDto.getReinsPolicyFee()){
                reinsPolicyFee.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
            }
        }else{
            throw new BusinessException("保单号"+reinsOverPolicyDto.getProposalNo()+"未能正常查询reinsPolicyFeeDto数据");
        }

        if(ObjectUtil.isNotNull(reinsPolicyInterfDto.getReinsPolicyPlan()) && ! reinsPolicyInterfDto.getReinsPolicyPlan().isEmpty()){
            // 更新中间表Plan
            for(ReinsPolicyPlan reinsPolicyPlan:reinsPolicyInterfDto.getReinsPolicyPlan()){
                reinsPolicyPlan.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
            }
        }else{
            throw new BusinessException("保单号"+reinsOverPolicyDto.getProposalNo()+"未能正常查询reinsPolicyPlanDto数据");
        }
        // 更新中间表Coins
        for(ReinsPolicyCoins reinsPolicyCoins:reinsPolicyInterfDto.getReinsPolicyCoins()){
            reinsPolicyCoins.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
        }
        // 更新中间表Limits
        for(ReinsPolicyLimit reinsPolicyLimit:reinsPolicyInterfDto.getReinsPolicyLimit()){
            reinsPolicyLimit.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
        }

        // 更新中间表Engage
        for(ReinsPolicyEngage reinsPolicyEngage:reinsPolicyInterfDto.getReinsPolicyEngage()){
            reinsPolicyEngage.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
        }
        // 更新中间表Ceded
        for(ReinsPolicyCeded reinsPolicyCeded:reinsPolicyInterfDto.getReinsPolicyCeded()){
            reinsPolicyCeded.setPolicyNo(reinsOverPolicyDto.getPolicyNo());
        }

    }

}
